package com.xplay.xpocker.room.message;

import java.math.BigDecimal;
import java.util.ArrayList;

import com.xplay.xpocker.constant.MessageNoticeEnum;
import lombok.Data;

/**
 * 客户端每一次收到消息 都会记录 syncVersion
 * 每次都会去判断 syncVersion 是否差距一个版本，如果差距一个版本
 * 同步更新房间内容
 * <p>
 * <p>
 * 但是有一些行为存在静默行为  怎么办 ：  比如
 * 一炮三响了，要等三个玩家做出决定，这个时候 房间内容发生了变更，
 * 但是实质上需要三个用户处理完成了再通知
 *
 * @param <T>
 */

@Data
public class MessageContent<T> {
    /**
     * 消息的目标对象
     * 如果为空 发送给其它所有人
     */
    BigDecimal messageToUid;
    /**
     * 谁执行了这个事件
     */
    BigDecimal messageFromUid;
    /**
     * 注意 不要随意更改这个版本号，用于客户端和服务器同步使用
     * 像 语音、文本消息。本质上是没有改变游戏所有内容的
     * 不建议更改版本号
     */
    int syncVersion;
    // 消息发送给谁   所有 当前人   其它人？？？？
    MessageNoticeEnum mnEnum;
    // 房间号是什么
    String roomCode;
    // 消息类型
    Integer type;
    // 具体内容....;
    T body;


    public static <T> Builder builder(String roomCode, Integer type, BigDecimal messageToUid, MessageNoticeEnum mnEnum) {
        return new Builder<T>(roomCode, type, messageToUid, mnEnum);
    }

    @Override
    public String toString() {
        return "MessageContent{" +
                "messageToUid=" + messageToUid +
                ", messageFromUid=" + messageFromUid +
                ", syncVersion=" + syncVersion +
                ", mnEnum=" + mnEnum +
                ", roomCode='" + roomCode + '\'' +
                ", type=" + type +
                ", body=" + body +
                '}';
    }

    public MessageContent() {
        mnEnum = MessageNoticeEnum.ALL;
    }

    public MessageContent(BigDecimal messageFromUid, BigDecimal messageToUid, Integer type, T body) {
        this.messageFromUid = messageFromUid;
        this.messageToUid = messageToUid;
        this.type = type;
        this.body = body;
    }

    public MessageContent(T body) {
        this.body = body;
    }

    public MessageContent(Integer type, T body) {
        this.type = type;
        this.body = body;
    }


    public static class Builder<T> {
        private MessageContent<T> content;

        Builder(MessageContent<T> content) {
            this.content = content;
        }

        public Builder(String roomCode, Integer type, BigDecimal messageToUid, MessageNoticeEnum mnEnum) {
            MessageContent<T> content = new MessageContent<T>();
            content.setRoomCode(roomCode);
            content.setMessageToUid(messageToUid);
            content.setType(type);
            content.setMnEnum(mnEnum);
            this.content = content;
        }

        public static <T> Builder<T> builder() {
            return new MessageContent.Builder<T>(new MessageContent<T>());
        }

        public Builder<T> setBody(T data) {
            content.setBody(data);
            return this;
        }

        /**
         * @param roomCode     房间号
         * @param type         消息类型
         * @param messageToUid 消息发送给哪个用户
         * @param mnEnum       发送类型
         * @return
         */

        public Builder<T> init(String roomCode, Integer type, BigDecimal messageToUid, MessageNoticeEnum mnEnum) {
            content.setRoomCode(roomCode);
            content.setMessageToUid(messageToUid);
            content.setType(type);
            content.setMnEnum(mnEnum);
            return this;
        }

        public static <T> Builder<T> builder(String roomCode, Integer type, BigDecimal messageToUid, MessageNoticeEnum mnEnum) {
            MessageContent<T> content = new MessageContent<T>();
            content.setRoomCode(roomCode);
            content.setMessageToUid(messageToUid);
            content.setType(type);
            content.setMnEnum(mnEnum);
            return new Builder<T>(content);
        }

        public static <T> Builder<T> builder(String roomCode, Integer type, BigDecimal messageFromUid, BigDecimal messageToUid, MessageNoticeEnum mnEnum) {
            MessageContent<T> content = new MessageContent<T>();
            content.setRoomCode(roomCode);
            content.setMessageFromUid(messageFromUid);
            content.setType(type);
            content.setMessageToUid(messageToUid);
            content.setMnEnum(mnEnum);
            return new Builder<T>(content);
        }

        public Builder<T> init(String roomCode, Integer type, BigDecimal messageFromUid, BigDecimal messageToUid, MessageNoticeEnum mnEnum) {
            content.setRoomCode(roomCode);
            content.setMessageFromUid(messageFromUid);
            content.setType(type);
            content.setMessageToUid(messageToUid);
            content.setMnEnum(mnEnum);
            return this;
        }

        /**
         * 对于消息发送给前端来说,这里的sourceId应该是事件执行人
         * 比如某个用户做了摸牌操作
         *
         * @param uid
         * @return
         */

        public Builder<T> setMessageFromUid(BigDecimal uid) {
            content.setMessageFromUid(uid);
            return this;
        }

        public Builder<T> setRoomCode(String roomCode) {
            content.setRoomCode(roomCode);
            return this;
        }

        public Builder<T> setType(Integer type) {
            content.setType(type);
            return this;
        }

        /**
         * 指定消息接收对象
         * 当MessageNoticeEnum CURRENT的时候
         * 只会发送消息给这个 target的人
         *
         * @param uid
         * @return
         */

        public Builder<T> setMessageToUid(BigDecimal uid) {
            content.setMessageToUid(uid);
            return this;
        }

        public Builder<T> setMnEnum(MessageNoticeEnum mnEnum) {
            content.setMnEnum(mnEnum);
            return this;
        }

        public MessageContent<T> build() {
            if (content.getMnEnum() == null) {
                throw new RuntimeException("消息发送类型不能为空,ALL,OTHER,CURRENT");
            }
            if (content.getMnEnum().equals(MessageNoticeEnum.CURRENT) && content.getMessageToUid() == null) {
                throw new RuntimeException("指定消息发送人不能为空.....");
            }

            if (content.getMnEnum().equals(MessageNoticeEnum.OTHER) && content.getMessageToUid() == null) {
                throw new RuntimeException("排除消息接收人不能为空.....");
            }
            return this.content;
        }

    }
}
